package com.lifesting.tool.encoding;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.mapping.ResourceTraversal;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.IStructuredSelection;

public class SetEncodingJob extends Job {
	private IStructuredSelection selection;
	private List<Setting> settings;

	class ChangeEncodingVisitor implements IResourceVisitor {
		private IProgressMonitor monitor;

		public ChangeEncodingVisitor(IProgressMonitor monitor) {
			this.monitor = monitor;
		}

		public boolean visit(IResource resource) throws CoreException {
			if (this.monitor.isCanceled()) {
				return false;
			}
			return SetEncodingJob.this.setEncoding(this.monitor, resource);
		}
	}

	public SetEncodingJob(IStructuredSelection selection) {
		super("Setting file encoding");
		this.selection = selection;
		this.settings = new ArrayList();
		loadSetting();
	}

	private void loadSetting() {
		IProject proj = ((IResource) this.selection.getFirstElement()).getProject();
		Activator.loadSetting(proj.getName(), this.settings);
	}

	protected IStatus run(IProgressMonitor monitor) {
		monitor.beginTask("Setting file encoding", -1);
		IResource[] resources = new IResource[this.selection.size()];
		try {
			System.arraycopy(this.selection.toArray(), 0, resources, 0, this.selection.size());
			new ResourceTraversal(resources, 2, 0).accept(new ChangeEncodingVisitor(monitor));
		} catch (CoreException e) {
			Activator.logException(e);
		}
		for (IResource s : resources) {
			try {
				s.refreshLocal(2, monitor);
			} catch (CoreException e) {
				Activator.logException(e);
			}
		}
		monitor.done();
		return Status.OK_STATUS;
	}

	private boolean setEncoding(IProgressMonitor monitor, IResource res) {
		if ((res instanceof IFile)) {
			IFile file = (IFile) res;
			monitor.subTask("Process file " + file.getName());
			String suffix = file.getFileExtension();
			if ((suffix != null) && (!file.isLinked()) && (!file.isPhantom())) {
				for (Setting setting : this.settings) {
					if (setting.getSuffix().equals(suffix)) {
						try {
							String encoding = file.getCharset();
							if ((!setting.getCurrentEncoding().equalsIgnoreCase(encoding))
									&& (!setting.getCurrentEncoding().equals("all"))) {
								break;
							}
							if ((setting.isConvertCharacter()) && (!file.isReadOnly())) {
								InputStream inputstream = file.getContents();
								IFileStore store = EFS.getStore(file.getLocationURI());
								int file_size = (int) store.fetchInfo().getLength();
								byte[] buffer = new byte[file_size];
								inputstream.read(buffer);

								String orignal = new String(buffer, encoding);

								ByteArrayInputStream byte_input = new ByteArrayInputStream(
										orignal.getBytes(setting.getConvertedEncoding()));

								file.setContents(byte_input, 1, monitor);
							}
							file.setCharset(setting.getConvertedEncoding(), monitor);
						} catch (CoreException e) {
							Activator.logException(e);
						} catch (IOException e) {
							Activator.logException(e);
						}
					}
				}
			}
			return false;
		}
		return true;
	}
}
